import { assetManager } from 'cc';
import { AudioClip } from 'cc';
import { AudioSource } from 'cc';
import { Asset } from 'cc';
import { _decorator, Component, Node } from 'cc';
import { GameManager, IUpdatable, regGameManager } from '../../extensions/cocos-scaffold-3x/assets/GameManager';
import { director } from 'cc';
import { EBundleName, gg } from '../Game';
import { Static } from '../../extensions/cocos-scaffold-3x/assets/Static';
import { AssetsManager } from '../../extensions/cocos-scaffold-3x/assets/manger/AssetsManager';
const { ccclass, property } = _decorator;

@regGameManager()
export class AudioManager extends GameManager implements IUpdatable {
    private effectSourcePool: AudioSource[] = [];


    private effectSourceIndex: number = 0;
    get effectVolume() {
        return 1
    }
    public async initialize() {
        this.audioRootNode = new Node("AudioManager");
        this.bgmNode = new Node("BGM");
        director.addPersistRootNode(this.audioRootNode)
        director.addPersistRootNode(this.bgmNode)

        this.loadAudios().then(() => {
        })

        for (let i = 0; i < 15; i++) {
            this.effectSourcePool.push(this.createAudioSource(this.audioRootNode, this.effectVolume));
        }
        Static.eventTarget.on("playSoundEff", (name) => {
            this.playEffect(name)
        }, this)
    }
    public destroy(): void {
        Static.eventTarget.targetOff(this)
    }

    loadAudios(path = "sound", bundleName = "resources") {
        return new Promise<void>(async (resolve, reject) => {
            const bundle = await AssetsManager.getBundle(bundleName)
            bundle.loadDir(path, AudioClip, (err, clips) => {
                if(clips){
                    clips.forEach(clip => {
                        this.clips[clip.name] = clip;
                    })
                }
                resolve()
            })
        })

    }

    bgmNode: Node;
    audioRootNode: Node;
    /**音乐静音 */
    get musicDisabled(): boolean {
        return false
    }
    /**音效静音 */
    get soundEffectDisabled(): boolean {
        return false
    }

    //缓存的clip对象
    clips: any = {};


    playEffect(n: string, volume = 1) {

        if (this.soundEffectDisabled) {
            return;
        }
        let clip: AudioClip = this.getClip(n)
        if (!clip) {
            console.error('audio ' + n + " not has.");
            return null;
        }
        const source = this.getNextEffectSource();
        source.clip = clip
        source.play();
    }



    bgm: AudioSource;

    lastPlayBgmName = "bgm"

    forceStoped = false
    playBGM(n: string = "bgm") {
        this.lastPlayBgmName = n
        if (this.musicDisabled) {
            return;
        }
        if (this.bgm && this.bgm.name != n) {
            this.stopBGM()
        }
        if (!this.bgm) {
            this.bgm = this.bgmNode.addComponent(AudioSource);
            this.bgm.clip = this.getClip(n);
            this.bgm.loop = true;
            // this.bgm.node.on(AudioSource.EventType.ENDED, this.bgmLoop, this);
        }

        this.forceStoped = false
        if (this.bgm && !this.bgm.playing) {
            this.bgm.play();
        }
    }

    resumeBgm() {
        this.playBGM(this.lastPlayBgmName)
    }

    stopBGM() {
        this.forceStoped = true
        if (this.bgm) {
            //this.bgm.node.off(AudioSource.EventType.ENDED, this.bgmLoop, this);
            this.bgm.stop();
            this.bgm.destroy();
            this.bgm = null;
        }
    }


    f: number = 0;

    update(deltaTime: number) {
        this.f++;
        if (this.f % 2 == 0) {
            this.checkBgmPlay()

        }
    }

    checkBgmPlay() {
        if (this.forceStoped) {
            return
        }
        if (this.bgm
            && !this.musicDisabled
            && !this.bgm.playing
            || !this.bgm
        ) {
            this.playBGM(this.lastPlayBgmName)
        } else if (this.bgm
            && this.musicDisabled
            && this.bgm.playing
        ) {
            this.bgm.stop();
        }
    }



    stopEffect(name: string) {
        console.log("stopEffect------", name);

        for (let index = this.effectSourcePool.length - 1; index >= 0; index--) {
            const audioSource = this.effectSourcePool[index];
            if (audioSource.clip.name == name) {
                console.log("stopEffect------", index);
                audioSource.stop()
            }
        }


    }

    _clips: any = {};

    getClip(n: string) {
        if (!this._clips[n]) {
            this._clips[n] = <AudioClip>assetManager.assets.find((val: Asset) => {
                return val.name == n
            })
        }
        return this._clips[n];
    }



    /**

    * 创建音频源

    * @param node 节点

    * @param volume 音量

    * @returns AudioSource 音频源组件

    */

    private createAudioSource(node: Node, volume: number): AudioSource {

        const source = node.addComponent(AudioSource);

        source.loop = false;

        source.playOnAwake = false;

        source.volume = volume;

        return source;

    }

    /**
    
         * 获取下一个音效组件
    
         * @returns AudioSource 下一个音效组件
    
         */

    private getNextEffectSource(): AudioSource {

        const source = this.effectSourcePool[this.effectSourceIndex];
        // if(source.clip){
        //     source.stop()
        //     source.clip.destroy()
        //     source.clip = null
        // }


        this.effectSourceIndex = (this.effectSourceIndex + 1) % this.effectSourcePool.length;

        return source;

    }
}
